package com.qianfeng.ssmplatform.strategy.service.impl;


//
//                            _ooOoo_  
//                           o8888888o  
//                           88" . "88  
//                           (| -_- |)  
//                            O\ = /O  
//                        ____/`---'\____  
//                      .   ' \\| |// `.  
//                       / \\||| : |||// \  
//                     / _||||| -:- |||||- \  
//                       | | \\\ - /// | |  
//                     | \_| ''\---/'' | |  
//                      \ .-\__ `-` ___/-. /  
//                   ___`. .' /--.--\ `. . __  
//                ."" '< `.___\_<|>_/___.' >'"".  
//               | | : `- \`.;`\ _ /`;.`/ - ` : | |  
//                 \ \ `-. \_ __\ /__ _/ .-` / /  
//         ======`-.____`-.___\_____/___.-`____.-'======  
//                            `=---='  
//  
//         .............................................  
//                  佛祖镇楼            BUG辟易  
//          佛曰:  
//                  写字楼里写字间，写字间里程序员；  
//                  程序人员写程序，又拿程序换酒钱。  
//                  酒醒只在网上坐，酒醉还来网下眠；  
//                  酒醉酒醒日复日，网上网下年复年。  
//                  但愿老死电脑间，不愿鞠躬老板前；  
//                  奔驰宝马贵者趣，公交自行程序员。  
//                  别人笑我忒疯癫，我笑自己命太贱；  


import com.qianfeng.smsplatform.common.constants.CacheConstants;
import com.qianfeng.smsplatform.common.constants.StrategyConstants;
import com.qianfeng.smsplatform.common.model.Standard_Submit;
import com.qianfeng.ssmplatform.strategy.service.FilterChain;
import com.qianfeng.ssmplatform.strategy.service.IQueueService;
import com.qianfeng.ssmplatform.strategy.service.api.CacheService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Set;
import java.util.UUID;

/**
 * Created by jackiechan on 2021/4/6 20:05
 *
 * @author jackiechan
 */
@Service
public class SmsLimitFilter implements FilterChain {
    @Autowired
    private CacheService cacheService;
    static final Logger LOGGER = LoggerFactory.getLogger(SmsLimitFilter.class);
    @Autowired
    private IQueueService queueService;
    /**
     * 进行限流的操作
     * 我们的限流是什么?具体参考README.MD
     *
     * @param submit
     * @return
     * @throws Exception
     */
    @Override
    public boolean dealSms(Standard_Submit submit) throws Exception {
        //限流规则, 针对同一个手机号每分钟不能超过三次, 每小时不能超过五次,每天不能超过 10 次,具体次数可以自己定义,通过管理平台可以设置
        //我们的平台可以有很多个客户, 比如知乎是我们的客户, B 站是我们的客户,他们给同一个用户发送短信算不算一个限流? 肯定不算
        //查看有没有超出分钟的限制,超出了直接返回
        long currentTimeMillis = System.currentTimeMillis();//系统的当前时间
        long oneMinAgo = currentTimeMillis - 60000;//一分钟以前的时间
        //从保存限制的地方按照当前的客户和手机号查询已经发送的数量

        Set<Object> objectSet = cacheService.zRangeByScore(CacheConstants.CACHE_PREFIX_SMS_LIMIT + submit.getClientID() + submit.getDestMobile(), oneMinAgo, currentTimeMillis);
        if (objectSet!=null&&objectSet.size()>=3) {
            //超出一分钟的限制
            LOGGER.error("超出一分钟的限制");
            //短信不可以发送,应该返回相应的操作
        }else{
            //查询有没有超出小时的限制,超出直接返回
            long oneHourAgo = currentTimeMillis - 60000*60;//一小时以前的时间
            objectSet = cacheService.zRangeByScore(CacheConstants.CACHE_PREFIX_SMS_LIMIT + submit.getClientID() + submit.getDestMobile(), oneHourAgo, currentTimeMillis);
            if (objectSet!=null&&objectSet.size()>=5) {
                //超出一分钟的限制
                LOGGER.error("超出一小时的限制");
                //短信不可以发送,应该返回相应的操作
            }else{
                //查询有没有超出天的限制,超出直接返回
                long oneDayAgo = currentTimeMillis - 60000*60*24;//一小时以前的时间
                objectSet = cacheService.zRangeByScore(CacheConstants.CACHE_PREFIX_SMS_LIMIT + submit.getClientID() + submit.getDestMobile(), oneDayAgo, currentTimeMillis);
                if (objectSet!=null&&objectSet.size()>=10) {
                    //超出一分钟的限制
                    LOGGER.error("超出一天的限制");
                    //短信不可以发送,应该返回相应的操作
                }else{
                    //没有超出限制,应该发送短信
                    LOGGER.error("没有超出限制,可以发送短信");
                    //发送短信(继续下一步)
                    //发送后保存发送记录
                    cacheService.zAdd(CacheConstants.CACHE_PREFIX_SMS_LIMIT + submit.getClientID() + submit.getDestMobile(), UUID.randomUUID().toString(), currentTimeMillis);
                    return true;
                }
            }
        }

        queueService.sendSmsReport(submit, StrategyConstants.STRATEGY_ERROR_LIMIT);
        return false;
    }
}
